home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
JPDOOR32.ARJ
/
MULTI.DOC
< prev
next >
Wrap
Text File
|
1992-02-26
|
16KB
|
393 lines
┌──────────────────────────────────────────────┐
│ MOTOR CITY SOFTWARE │
│ ┌──────────────────────────────────────┐ │
│ │ JPDoor - Version 3.1 SE │ │
│ │ Copyright 1990 - 1992 │ │
│ │ ┌──────────┐ │ │
│ │ │\ │ │ │
│ │ │ \ │ │ │
│ │ │ \ P │ │ │
│ │ │ \ A │ │ │
│ │ │ │ S │ │ │
│ │ │ │ C │ │ │
│ │ 5.5 │ │ A │ 6.0 │ │
│ │ │ o│ L │ │ │
│ │ │ │ │ │ │
│ │ \ │──────┘ │ │
│ │ \ │ │ │
│ └──────────────\ │─────────────────────┘ │
│ The Ultimate \│ Door Writing Unit. │
└────────────────────┴─────────────────────────┘
This file contains information on writing doors that work in a multi-node
environment. While your door may not be multi-player, we would recommend
that you read over the following information anyways.
With the number of Multi-Node BBS's steadily increasing, we felt it was
very important to make it easy on the programmer to make his doors multi-
node aware. This release of JPDoor has many new features that make it easy
to write programs which work in a multi-node environment, even if you are
not running multi-node yourself. We have taken this one step further, in
that you can easily write doors which allow players to compete head-to-head!
While some of this may sound complex, it really is quite simple.
JPDoor will only allow multi-player games on RemoteAccess V 1.xx and
QuickBBS V 2.75. Future versions will also include full support for PCBoard.
SHARE MUST BE LOADED!
Some of the multi-node capabilities included are:
- Listing Other Users Currently Online
- Sending Online Messages to other users
- Determining the node number that the current user is logged onto
- Determining who is logged onto other nodes
- File/Record locking routines so your door can run on more than one node
at a time
- A method to ensure that your door is only run on one node at a time if
need be
- The ability for two nodes to pass data back and forth
This document is going to try to explain how to write a door which allows
two players, and passes game data back and forth between them. These
routines have been tested extensively, and while they appear to be working
fine, there exists a possibility that there are systems which may have
problems. Because of this, we will be working closely with anyone having
problems. If problems are discovered, then beta versions will be made
available to any registered user who requests it.
To start with, some basic concepts...
Multi-player doors will only work with QBBS 2.75 or RA 1.xx
All data is passed in a file called JPDOOR.USE which will be
created in the system directory pointed to by either the RA
or QUICK environment variable.
JPDoor has defined the structure for this file as follows:
TYPE
JPUseData = Array[1..2048] of Byte;
JPUSErecord = record
Name : String[35];
Line : Byte;
DoorName : String[20];
Status : Byte;
MaxPlayers : Byte;
Filler : Array[1..13] of byte;
MultiNode : Boolean;
PID : Integer;
Data : JPUseData;
End;
{ Status Byte : 0 - New Record Added }
{ 1 - New Data Written }
{ 2 - Data Has Been Read }
Var
JPUse : JPUseRecord; { Variable to hold MY record}
JPUseOther : JPUseRecord; { Variable to hold OTHER users record }
Lets look at each field :
Name - This is the name of the user currently online
Line - This is the node number the user is on. This does
not default to 1 like the dorinfo1.def does, and you
can get the users node with the function GetNode.
GetNode will simply search USERON.BBS for the users
name as defined in dorinfo1.def, and return the actual
node he is loggend onto.
DoorName - This is the name of your door. Its best to keep this to
15 characters or less. When JPDoor's Whoson procedure is
called, it will display this so other users can see that
your door is in use.
Status - This is used internally, and you need not worry about it.
The following values are used :
0 - New Record Added
1 - New Data Written
2 - Data Has Been Read
MaxPlayers - This contains the maximum number of users who can play
at one time. Currently, JPDoor will only support 2
players, but this will be increased in future versions.
MultiNode - True if your door allows more than one user to run the
door at the same time.
PID - If your Door is a multi-player door, then you MUST apply
for a Product ID code. You must be registered in order
to receive one. In order to test your door, use a PID of
0. If you attempt to use any other value, it will abort!
Data - This is where all the data is passed back and forth between
two nodes. This is explained in detail below.
A note about PIDs.
The PID is used to ensure that you only try to read data
written by YOUR door on another node. You dont want a
battleship door reading a data file from an X's and O's
door etc... The PID is validated internally by JPDoor.
The Value of 0 is for test purposes only, as we do not
want to force you to register BEFORE you can test it.
If you release a multi-player door using a 0 for a PID,
then you run the risk of it conflicting with other doors!
You will need a PID for each and every different multi-
player game you write.
There is no fee for registering a PID, and there is no
limit to the number of PIDs you may register, but you
must be a registered user of JPDoor.
PID 0 is ONLY for testing purposes, and you are expected
to register JPDoor and request a PID BEFORE you release
your door.
How it all works.
First, you need to decide what data you wish to pass back and forth.
Define a structure that is exactly 2048 bytes in size. An example
from my BattleShips door follows:
TYPE
Grid = Array[1..9,0..9] of Char; { Letter,Number }
NodeData = Record
Status : Byte;
PlayerName : String[25];
SeaGrid : Grid;
ShotN,
ShotL : Byte;
ShipHits : Array[1..6] of byte;
ChatLine : String[78];
Local : Boolean;
Filler : Array[1..1843] of Byte; {this is added to ensure that}
{ the record is exactly 2048 }
{ bytes in length}
End;
Once you have defined this structure, you need to be able to reference
it two ways. You need to be able to modify each field, and also be
able to reference it within the JPUseRecord. This is accomplished by
using pointers.
You must also remember that you need to reference YOUR nodes data, as
well as the OTHER nodes data.
Var
JPD : JPUseData; { MY nodes Data as a field in JPUseRecord}
OJPD : JPUseData; { OTHER nodes data as a field in JPUseRecord}
NDPtr : ^NodeData; { My Nodes Data a I defined it}
ONDPtr : ^NodeData; { Other nodes data as I defined it}
Now JPD and OJPD are an Array[1..2048] of Byte;
NDPtr and ONDPtr are pointers to the Type we defined above.
All of these structures occupy the same amount of space, 2048 bytes.
We can now tell our program that NDPtr points to the same location in
memory where the variable JPD is stored, and ONDPtr points to the same
location in memory where the variable OJPD is stored. If your not
familiar with pointers, don't worry, I'm no pro either <grin>.
Basically what we are doing, is saying that NDPtr points to the
location where the variable JPD is located in memory. Because they
are the same size, we can now reference the same data in two ways!
NDPtr := @JPD; {OUR nodes data}
ONDPtr := @OJPD; {OTHER nodes data}
If we want to put the users name into the JPDoor.Use file, we simply
refer to the name field defined in JPUseRecord as JPD.NAME
To reference a field in OUR defined structure, we use the pointer.
For example if I wish to pass a short note to the user on the other
node, I can use the CHATLINE field I defined in MY structure.
NDPtr^.ChatLine := 'Hi there...';
Because this points to JPD which is 2048 bytes in size, and ChatLine
starts at 126 bytes into MY structure, is is saved in the same memory
location as JPD, but at offset 126.
Now JPD contains this string starting at byte 126.
Like I said, it may sound confusing, but don't worry about it. Its
kinda like driving a car, you don't have to understand how it works
in order to use it, Afterall, thats what JPDoor is all about, making
it easy to do things you may not understand!
Adding a user to JPDOOR.USE
---------------------------
Function JPUseAdd : Boolean;
In your door, you need to add the user information to the JPDOOR.USE
file. This is done with the JPUseAdd function. If JPDOOR.USE does
not exist, it will be created. This function will count the number of
nodes by counting the number of records in your USERON.BBS and one
record will be added to JPDOOR.USE for each one in USERON.BBS.
Here is a sample from my MAIN code:
BEGIN (* M A I N *)
ASSIGN(output,'') ;
REWRITE(output) ;
InitVars ;
GetDorInfo('1',DropPath) ;
NDPtr := @JPD; {Set the pointer to point to JPD}
ONDPtr := @OJPD;
FillChar(NDPtr^,SizeOf(NDPtr^),#0); {Fill the memory location with Nulls}
JPUse.Pid := 0; {Set Your PID - 0 if not registered}
JPUse.Name := UserName;
JPUse.MultiNode := True;
JPUse.DoorName := 'BattleShip';
JPUse.Line := GetNode;
NDPtr^.Status := 1;
JPUse.MaxPlayers := 2;
JPUse.Data := JPD; { Now move JPD into the JPUse.Data field}
If Not JPUseAdd then
Begin
CRLF ;
Display(0,15,0,'Motor City Battle Ships allows for two players at once,') ;
Display(0,15,0,'and there are currently two people playing.') ;
CRLF ;
HALT(0) ;
End;
You will notice that I set JPUse.MaxPlayers to 2 players. When JPUseAdd
is called, it counts the number of users already in JPDoor.Use with the
same PID, and if there are already MaxPlayers playing, JPUseAdd will
NOT add you, and will return False.
Removing a user from JPDOOR.USE
-------------------------------
Procedure JPUseExit;
When the user exists the door, under ANY circumstances, you MUST make
sure you remove him from the JPDOOR.USE file. This is done by adding
the JPUseExit procedure to your Terminate procedure as follows:
Procedure Terminate(n:byte) ;
begin
JPUseExit; {This ensures that the user is removed!}
case n of
0 : begin
CloseGame ;
LastComments ;
end ;
1 : begin
CloseGame ;
Writeln('■ Carrier lost') ;
end ;
2 : begin
CloseGame ;
Writeln('■ Time limit exceeded') ;
end ;
3 : begin
CloseGame ;
Writeln('■ User inactive') ;
end ;
4,
5,
6 : begin
end ;
7 : begin
CloseGame ;
Writeln('■ CTS timeout error') ;
End ;
else CloseGame ;
end ;
end ;
Updating Data in JPDOOR.USE
---------------------------
Procedure JPUseUpdate;
Data is passed to the other node by updating your JPUse.Data field,
so that the other node can read it. It is similar to the JPUseAdd
function except this is a procedure, and does not return any values.
You may find it easier to create a PlayerUpdate procedure as I did
in BattleShips:
Procedure UpDateMyData;
Begin
NDPtr^.Local := Local;
If Not SendChat then NDPtr^.ChatLine := '';
SendChat := False;
JPUse.Data := JPD;
JPUseUpDate;
End;
Your code would update any relevent fields, then call this procedure.
When you Update your data, JPUse.Status will be set to 1 signifying
that new data has been written to the file.
Getting Other Users Data from JPDOOR.USE
----------------------------------------
Function JPUseGet : Boolean;
JPUseGet will scan the JPDOOR.USE file for another user (it checks
the username) with the SAME PID as your door. If one is found, and
new data is read (JPUse.Status = 1) then JPUseGet returns TRUE and
the other users data is stored in the variable JPUseOther.
JPUseOther is exactly the same as JPUse, but is a seperate variable
to hold the other players data. Both are defined in JPDoor.
If there is no other user, then JPUseGet returns false, and the
variable is filled with nulls. If it finds a user, but no new data
is found, it returns false, and contains the same data as before the
call was made.
If you are waiting for the other player to take his turn, you may
simply keep calling this funtion until it returns TRUE.
The other players data is read the same as you write your data.
If JPUseGet then
Begin
OJPD := JPUseOther.Data; { Put OTHER users data into OJPD}
End;
To get his name : JPUseOther.Name
To Get his Node# : JPUseOther.Line
To Get his Chatline : ONDPtr^.ChatLine
etc...